﻿using System;
using System.Collections.Generic;
using System.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Windows.ApplicationModel.Background;
using Windows.ApplicationModel.Core;
using Windows.Data.Xml.Dom;
using Windows.Security.Authentication.Identity.Provider;
using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using Windows.Storage.Streams;
using Windows.UI.Core;
using Windows.UI.Notifications;
using MyHelloWinJson;
using MyHelloWinDevice;
using Windows.Devices.Enumeration;
using Windows.Storage;

namespace Tasks
{
    class HelloWinMonitor
    {
        ManualResetEvent m_opCompletedEvent = null;

        public void DealWithUnlock()
        {
            m_opCompletedEvent = new ManualResetEvent(false);
            SecondaryAuthenticationFactorAuthentication.AuthenticationStageChanged += OnStageChanged;
            m_opCompletedEvent.WaitOne();
        }

        // 这个函数是系统通知后台进程当前状态变化的函数
        async void OnStageChanged(Object sender, SecondaryAuthenticationFactorAuthenticationStageChangedEventArgs args)
        {
            // 表示正在等待解锁。
            if (args.StageInfo.Stage == SecondaryAuthenticationFactorAuthenticationStage.WaitingForUserConfirmation)
            {
                //ShowToastNotification("显示提示信息");
                // 这个实在登录界面显示提示信息用的
                String deviceName = "AlwaysKing.";
                await SecondaryAuthenticationFactorAuthentication.ShowNotificationMessageAsync(
                    deviceName,
                    SecondaryAuthenticationFactorAuthenticationMessage.SwipeUpWelcome);
            }
            else if (args.StageInfo.Stage == SecondaryAuthenticationFactorAuthenticationStage.CollectingCredential)
            {
                PerformAuthentication();
            }
            else
            {
                if (args.StageInfo.Stage == SecondaryAuthenticationFactorAuthenticationStage.StoppingAuthentication)
                {
                    SecondaryAuthenticationFactorAuthentication.AuthenticationStageChanged -= OnStageChanged;
                    m_opCompletedEvent.Set();
                }

                SecondaryAuthenticationFactorAuthenticationStage stage = args.StageInfo.Stage;
            }
        }

        // 开始判断是否能解锁设备
        async void PerformAuthentication()
        {
            // 判断当前是不是正在解锁
            SecondaryAuthenticationFactorAuthenticationStageInfo authStageInfo = await SecondaryAuthenticationFactorAuthentication.GetAuthenticationStageInfoAsync();
            if (authStageInfo.Stage != SecondaryAuthenticationFactorAuthenticationStage.CollectingCredential)
            {
                // 状态不对就直接报错
                //ShowToastNotification("Unexpected!");
                //throw new Exception("Unexpected!");
                return;
            }
            DebugInfo.ShowToastNotification("MyHelloWin");

            IReadOnlyList<SecondaryAuthenticationFactorInfo> deviceList = await SecondaryAuthenticationFactorRegistration.FindAllRegisteredDeviceInfoAsync(
            SecondaryAuthenticationFactorDeviceFindScope.AllUsers);

            for (int i = 0; i < deviceList.Count; i++)
            {
                SecondaryAuthenticationFactorInfo deviceInfo = deviceList.ElementAt(i);

                byte[] combinedDataArray;
                CryptographicBuffer.CopyToByteArray(deviceInfo.DeviceConfigurationData, out combinedDataArray);
                string JS = System.Text.Encoding.UTF8.GetString(combinedDataArray);
                JsonData Dat = CMyHelloWinJson.ParesToData(JS);

                if (Dat == null)
                {
                    continue;
                }

                if (Dat.CanUnLock)
                {
                    UnLockWithDevices(deviceInfo.DeviceId, Dat);
                }
            }
        }

        public async void UnLockWithDevices(string m_selectedDeviceId, JsonData Dat)
        {
            //DebugInfo.ShowToastNotification(Dat.DeviceID);

            // 生成用于通讯的随即密钥
            IBuffer svcNonce = CryptographicBuffer.GenerateRandom(32);

            // 开始验证
            SecondaryAuthenticationFactorAuthenticationResult authResult = await SecondaryAuthenticationFactorAuthentication.StartAuthenticationAsync(
                m_selectedDeviceId, svcNonce);

            if (authResult.Status != SecondaryAuthenticationFactorAuthenticationStatus.Started)
            {
                return;
            }

            byte[] deviceKeyArray = System.Text.Encoding.UTF8.GetBytes(Dat.DeviceKey);
            byte[] authKeyArray = System.Text.Encoding.UTF8.GetBytes(Dat.AuthKey);

            // Create device key and authentication key
            IBuffer deviceKey = CryptographicBuffer.CreateFromByteArray(deviceKeyArray);
            IBuffer authKey = CryptographicBuffer.CreateFromByteArray(authKeyArray);

            // Calculate the HMAC
            MacAlgorithmProvider hMACSha256Provider = MacAlgorithmProvider.OpenAlgorithm(MacAlgorithmNames.HmacSha256);

            CryptographicKey deviceHmacKey = hMACSha256Provider.CreateKey(deviceKey);
            IBuffer deviceHmac = CryptographicEngine.Sign(deviceHmacKey, authResult.Authentication.DeviceNonce);

            // sessionHmac = HMAC(authKey, deviceHmac || sessionNonce)
            IBuffer sessionHmac;
            byte[] deviceHmacArray = { 0 };
            CryptographicBuffer.CopyToByteArray(deviceHmac, out deviceHmacArray);

            byte[] sessionNonceArray = { 0 };
            CryptographicBuffer.CopyToByteArray(authResult.Authentication.SessionNonce, out sessionNonceArray);

            byte[] combinedDataArray = new byte[deviceHmacArray.Length + sessionNonceArray.Length];
            for (int index = 0; index < deviceHmacArray.Length; index++)
            {
                combinedDataArray[index] = deviceHmacArray[index];
            }
            for (int index = 0; index < sessionNonceArray.Length; index++)
            {
                combinedDataArray[deviceHmacArray.Length + index] = sessionNonceArray[index];
            }

            // Get a Ibuffer from combinedDataArray
            IBuffer sessionMessage = CryptographicBuffer.CreateFromByteArray(combinedDataArray);

            // Calculate sessionHmac
            CryptographicKey authHmacKey = hMACSha256Provider.CreateKey(authKey);
            sessionHmac = CryptographicEngine.Sign(authHmacKey, sessionMessage);

            SecondaryAuthenticationFactorFinishAuthenticationStatus authStatus = await authResult.Authentication.FinishAuthenticationAsync(deviceHmac, sessionHmac);

            if (authStatus != SecondaryAuthenticationFactorFinishAuthenticationStatus.Completed)
            {
                DebugInfo.ShowToastNotification("使用设备" + Dat.DeviceID + "解锁饿windows");
            }
        }
    }
}
